"""
配置模式定义

使用 Pydantic 定义配置文件的数据模式，提供验证和类型检查。
"""

from typing import Dict, List, Optional, Union
from pydantic import BaseModel, Field, validator
from enum import Enum
import os


class TimezoneMode(str, Enum):
    """时区模式枚举"""
    AUTO = "auto"
    UTC = "utc"
    LOCAL = "local"


class CompressionAlgorithm(str, Enum):
    """压缩算法枚举"""
    GZIP = "gzip"
    LZ4 = "lz4"
    NONE = "none"


class StorageBackend(str, Enum):
    """存储后端枚举"""
    LOCAL = "local"
    S3 = "s3"
    OSS = "oss"


class LogLevel(str, Enum):
    """日志级别枚举"""
    DEBUG = "DEBUG"
    INFO = "INFO"
    WARNING = "WARNING"
    ERROR = "ERROR"
    CRITICAL = "CRITICAL"


class ElasticsearchConfig(BaseModel):
    """Elasticsearch 连接配置"""
    hosts: List[str] = Field(default=["localhost:9200"], description="ES集群地址列表")
    username: Optional[str] = Field(default=None, description="用户名")
    password: Optional[str] = Field(default=None, description="密码")
    api_key: Optional[str] = Field(default=None, description="API Key")
    ssl_verify: bool = Field(default=True, description="是否验证SSL证书")
    timeout: int = Field(default=30, ge=1, le=300, description="连接超时时间(秒)")
    request_timeout: int = Field(default=60, ge=1, le=600, description="请求超时时间(秒)")
    max_retries: int = Field(default=3, ge=0, le=10, description="最大重试次数")


class TimezoneConfig(BaseModel):
    """时区配置"""
    source: Union[TimezoneMode, str] = Field(default=TimezoneMode.AUTO, description="源时区")
    target: str = Field(default="UTC", description="目标时区")
    handle_dst: bool = Field(default=True, description="是否处理夏令时")


class TimeFormatsConfig(BaseModel):
    """时间格式配置"""
    auto_detect: bool = Field(default=True, description="是否自动检测格式")
    supported_formats: List[str] = Field(
        default=[
            "strict_date_optional_time",
            "epoch_millis",
            "epoch_second",
            "yyyy-MM-dd HH:mm:ss",
            "yyyy/MM/dd HH:mm:ss"
        ],
        description="支持的时间格式列表"
    )


class TimeRangeConfig(BaseModel):
    """时间范围配置"""
    default_precision: str = Field(default="second", description="默认时间精度")
    include_boundaries: bool = Field(default=True, description="是否包含边界时间点")
    max_range_days: int = Field(default=365, ge=1, le=3650, description="最大时间范围(天)")

    @validator('default_precision')
    def validate_precision(cls, v):
        allowed = ['second', 'millisecond', 'microsecond']
        if v not in allowed:
            raise ValueError(f'precision must be one of {allowed}')
        return v


class TimeHandlingConfig(BaseModel):
    """时间处理配置"""
    default_time_field: str = Field(default="@timestamp", description="默认时间字段")
    auto_detect_time_field: bool = Field(default=True, description="是否自动检测时间字段")
    time_field_candidates: List[str] = Field(
        default=["@timestamp", "timestamp", "created_at", "updated_at", "event_time", "log_time"],
        description="时间字段候选列表"
    )
    timezone: TimezoneConfig = Field(default_factory=TimezoneConfig)
    formats: TimeFormatsConfig = Field(default_factory=TimeFormatsConfig)
    range: TimeRangeConfig = Field(default_factory=TimeRangeConfig)


class TimeBasedBackupConfig(BaseModel):
    """基于时间的备份配置"""
    enable_incremental: bool = Field(default=True, description="启用增量备份")
    overlap_buffer: str = Field(default="1h", description="重叠缓冲时间")
    sort_by_time: bool = Field(default=True, description="按时间排序导出")


class BackupConfig(BaseModel):
    """备份配置"""
    chunk_size: str = Field(default="100MB", description="分片大小")
    compression: CompressionAlgorithm = Field(default=CompressionAlgorithm.GZIP, description="压缩算法")
    parallel_workers: int = Field(default=4, ge=1, le=16, description="并行工作线程数")
    include_mappings: bool = Field(default=True, description="是否包含映射信息")
    time_based: TimeBasedBackupConfig = Field(default_factory=TimeBasedBackupConfig)

    @validator('chunk_size')
    def validate_chunk_size(cls, v):
        """验证分片大小格式"""
        import re
        pattern = r'^\d+(?:\.\d+)?[KMGT]?B$'
        if not re.match(pattern, v.upper()):
            raise ValueError('chunk_size must be in format like "100MB", "1.5GB"')
        return v


class TimeBasedRestoreConfig(BaseModel):
    """基于时间的恢复配置"""
    preserve_timestamps: bool = Field(default=True, description="保持原始时间戳")
    adjust_timezone: bool = Field(default=False, description="是否调整时区")
    validate_time_range: bool = Field(default=True, description="验证时间范围")


class RestoreConfig(BaseModel):
    """恢复配置"""
    batch_size: int = Field(default=1000, ge=1, le=10000, description="批量大小")
    parallel_workers: int = Field(default=2, ge=1, le=8, description="并行工作线程数")
    validate_data: bool = Field(default=True, description="是否验证数据")
    create_index: bool = Field(default=True, description="是否创建索引")
    time_based: TimeBasedRestoreConfig = Field(default_factory=TimeBasedRestoreConfig)


class LocalStorageConfig(BaseModel):
    """本地存储配置"""
    base_path: str = Field(default="./backups", description="基础路径")
    create_subdirs: bool = Field(default=True, description="是否创建子目录")


class CompressionConfig(BaseModel):
    """压缩配置"""
    algorithm: CompressionAlgorithm = Field(default=CompressionAlgorithm.GZIP, description="压缩算法")
    level: int = Field(default=6, ge=1, le=9, description="压缩级别")


class StorageConfig(BaseModel):
    """存储配置"""
    backend: StorageBackend = Field(default=StorageBackend.LOCAL, description="存储后端")
    local: LocalStorageConfig = Field(default_factory=LocalStorageConfig)
    compression: CompressionConfig = Field(default_factory=CompressionConfig)


class LoggingConfig(BaseModel):
    """日志配置"""
    level: LogLevel = Field(default=LogLevel.INFO, description="日志级别")
    file: Optional[str] = Field(default="es-archive.log", description="日志文件")
    max_size: str = Field(default="10MB", description="日志文件最大大小")
    backup_count: int = Field(default=5, ge=1, le=20, description="日志备份数量")
    time_format: str = Field(default="ISO8601", description="时间格式")
    include_timezone: bool = Field(default=True, description="是否包含时区信息")


class MonitoringConfig(BaseModel):
    """监控配置"""
    enable_progress: bool = Field(default=True, description="启用进度监控")
    enable_metrics: bool = Field(default=True, description="启用指标收集")
    metrics_interval: int = Field(default=10, ge=1, le=300, description="指标收集间隔(秒)")


class SecurityConfig(BaseModel):
    """安全配置"""
    mask_sensitive_data: bool = Field(default=True, description="掩码敏感数据")
    audit_log: bool = Field(default=True, description="启用审计日志")


class ConfigSchema(BaseModel):
    """完整配置模式"""
    elasticsearch: ElasticsearchConfig = Field(default_factory=ElasticsearchConfig)
    time_handling: TimeHandlingConfig = Field(default_factory=TimeHandlingConfig)
    backup: BackupConfig = Field(default_factory=BackupConfig)
    restore: RestoreConfig = Field(default_factory=RestoreConfig)
    storage: StorageConfig = Field(default_factory=StorageConfig)
    logging: LoggingConfig = Field(default_factory=LoggingConfig)
    monitoring: MonitoringConfig = Field(default_factory=MonitoringConfig)
    security: SecurityConfig = Field(default_factory=SecurityConfig)

    class Config:
        """Pydantic 配置"""
        extra = "forbid"  # 禁止额外字段
        validate_assignment = True  # 赋值时验证
